Užtikrinkite sklandų „WebGL“ programų veikimą. Šis išsamus vadovas nagrinėja „WebGL Sync Fences“ – esminį primityvą efektyviam GPU ir CPU sinchronizavimui įvairiose platformose ir įrenginiuose.
GPU ir CPU sinchronizavimo įvaldymas: išsami „WebGL Sync Fences“ apžvalga
Didelio našumo interneto grafikos srityje efektyvi komunikacija tarp centrinio procesoriaus (CPU) ir grafikos procesoriaus (GPU) yra nepaprastai svarbi. „WebGL“, „JavaScript“ API, skirta interaktyviai 2D ir 3D grafikai atvaizduoti bet kurioje suderinamoje interneto naršyklėje nenaudojant papildinių, remiasi sudėtingu konvejeriu. Tačiau būdingas asinchroninis GPU operacijų pobūdis gali sukelti našumo kliūtis ir vizualinius artefaktus, jei nėra atidžiai valdomas. Būtent čia sinchronizavimo primityvai, ypač „WebGL Sync Fences“ (sinchronizavimo tvoros), tampa nepakeičiamais įrankiais kūrėjams, siekiantiems sklandaus ir greitai reaguojančio atvaizdavimo.
Asinchroninių GPU operacijų iššūkis
Savo esme GPU yra labai lygiagretaus apdorojimo jėgainė, sukurta vykdyti grafikos komandas milžinišku greičiu. Kai jūsų „JavaScript“ kodas pateikia „WebGL“ piešimo komandą, ji nėra iš karto įvykdoma GPU. Vietoj to, komanda paprastai įdedama į komandų buferį, kurį GPU apdoroja savo tempu. Šis asinchroninis vykdymas yra esminis dizaino sprendimas, leidžiantis CPU tęsti kitų užduočių apdorojimą, kol GPU yra užsiėmęs atvaizdavimu. Nors tai naudinga, šis atskyrimas sukelia kritinį iššūkį: kaip CPU žino, kada GPU baigė tam tikrą operacijų rinkinį?
Be tinkamo sinchronizavimo, CPU gali pateikti naujas komandas, kurios priklauso nuo ankstesnio GPU darbo rezultatų, dar prieš baigiant tą darbą. Tai gali sukelti:
- Pasenusius duomenis: CPU gali bandyti nuskaityti duomenis iš tekstūros ar buferio, į kurį GPU vis dar rašo.
- Atvaizdavimo artefaktus: Jei piešimo operacijos nėra teisingai susektos, galite pastebėti vizualinius trikdžius, trūkstamus elementus ar neteisingą atvaizdavimą.
- Našumo sumažėjimą: CPU gali be reikalo sustoti, laukdamas GPU, arba, atvirkščiai, gali per greitai pateikti komandas, o tai lemia neefektyvų išteklių naudojimą ir nereikalingą darbą.
- Lenktynių sąlygas (Race Conditions): Sudėtingos programos, apimančios kelis atvaizdavimo etapus arba tarpusavio priklausomybes tarp skirtingų scenos dalių, gali kentėti nuo nenuspėjamo elgesio.
Pristatome „WebGL Sync Fences“: sinchronizavimo primityvas
Norint išspręsti šiuos iššūkius, „WebGL“ (ir jo pagrindiniai „OpenGL ES“ arba „WebGL 2.0“ atitikmenys) teikia sinchronizavimo primityvus. Tarp galingiausių ir universaliausių iš jų yra sinchronizavimo tvora (sync fence). Sinchronizavimo tvora veikia kaip signalas, kurį galima įterpti į GPU siunčiamą komandų srautą. Kai GPU pasiekia šią tvorą savo vykdymo eigoje, ji signalizuoja apie konkrečią sąlygą, leidžiančią CPU gauti pranešimą arba laukti šio signalo.
Įsivaizduokite sinchronizavimo tvorą kaip žymeklį, pastatytą ant konvejerio juostos. Kai ant juostos esantis daiktas pasiekia žymeklį, sumirksi lemputė. Procesą prižiūrintis asmuo gali nuspręsti, ar sustabdyti juostą, imtis veiksmų, ar tiesiog pripažinti, kad žymeklis buvo praeitas. „WebGL“ kontekste „konvejerio juosta“ yra GPU komandų srautas, o „sumirksinti lemputė“ yra sinchronizavimo tvoros signalizavimas.
Pagrindinės sinchronizavimo tvorų sąvokos
- Įterpimas: Sinchronizavimo tvora paprastai sukuriama ir įterpiama į „WebGL“ komandų srautą naudojant funkcijas, tokias kaip
gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0). Tai nurodo GPU signalizuoti tvorą, kai visos komandos, pateiktos prieš šį iškvietimą, bus baigtos. - Signalizavimas: Kai GPU apdoroja visas ankstesnes komandas, sinchronizavimo tvora tampa „signalizuota“. Ši būsena rodo, kad operacijos, kurias ji turėjo sinchronizuoti, buvo sėkmingai įvykdytos.
- Laukimas: Tada CPU gali patikrinti sinchronizavimo tvoros būseną. Jei ji dar nėra signalizuota, CPU gali pasirinkti arba laukti, kol ji bus signalizuota, arba atlikti kitas užduotis ir vėliau patikrinti jos būseną.
- Ištrynimas: Sinchronizavimo tvoros yra ištekliai ir turėtų būti aiškiai ištrintos, kai jų nebereikia, naudojant
gl.deleteSync(syncFence), kad būtų atlaisvinta GPU atmintis.
Praktinis „WebGL Sync Fences“ taikymas
Galimybė tiksliai valdyti GPU operacijų laiką atveria platų galimybių spektrą „WebGL“ programoms optimizuoti. Štai keletas įprastų ir paveikių naudojimo atvejų:
1. Pikselių duomenų nuskaitymas iš GPU
Vienas iš dažniausių scenarijų, kai sinchronizavimas yra kritiškai svarbus, yra tada, kai reikia nuskaityti duomenis iš GPU atgal į CPU. Pavyzdžiui, galbūt norėsite:
- Įdiegti papildomo apdorojimo efektus, kurie analizuoja atvaizduotus kadrus.
- Programiškai fiksuoti ekrano nuotraukas.
- Naudoti atvaizduotą turinį kaip tekstūrą vėlesniems atvaizdavimo etapams (nors kadrų buferio objektai (framebuffer objects) dažnai siūlo efektyvesnius sprendimus šiam tikslui).
Tipinė darbo eiga galėtų atrodyti taip:
- Atvaizduoti sceną į tekstūrą arba tiesiai į kadrų buferį.
- Įterpti sinchronizavimo tvorą po atvaizdavimo komandų:
const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0); - Kai reikia nuskaityti pikselių duomenis (pvz., naudojant
gl.readPixels()), turite užtikrinti, kad tvora būtų signalizuota. Tai galite padaryti iškviesdamigl.clientWaitSync(sync, 0, gl.TIMEOUT_IGNORED). Ši funkcija blokuos CPU giją, kol tvora bus signalizuota arba pasibaigs laukimo laikas. - Po to, kai tvora signalizuota, saugu iškviesti
gl.readPixels(). - Galiausiai, ištrinkite sinchronizavimo tvorą:
gl.deleteSync(sync);
Globalus pavyzdys: Įsivaizduokite realaus laiko bendradarbiavimo projektavimo įrankį, kuriame vartotojai gali dėti anotacijas ant 3D modelio. Jei vartotojas nori užfiksuoti dalį atvaizduoto modelio, kad pridėtų komentarą, programa turi nuskaityti pikselių duomenis. Sinchronizavimo tvora užtikrina, kad užfiksuotas vaizdas tiksliai atspindėtų atvaizduotą sceną, užkertant kelią neužbaigtų ar sugadintų kadrų fiksavimui.
2. Duomenų perdavimas tarp GPU ir CPU
Be pikselių duomenų nuskaitymo, sinchronizavimo tvoros taip pat yra labai svarbios perduodant duomenis bet kuria kryptimi. Pavyzdžiui, jei atvaizduojate į tekstūrą ir vėliau norite naudoti tą tekstūrą vėlesniame atvaizdavimo etape GPU, paprastai naudojate kadrų buferio objektus (FBO). Tačiau, jei reikia perkelti duomenis iš tekstūros GPU atgal į buferį CPU (pvz., sudėtingiems skaičiavimams arba norint juos išsiųsti kitur), sinchronizavimas yra esminis.
Modelis yra panašus: atlikite atvaizdavimo ar GPU operacijas, įterpkite tvorą, palaukite tvoros ir tada inicijuokite duomenų perdavimą (pvz., naudojant gl.readPixels() į tipizuotą masyvą).
3. Sudėtingų atvaizdavimo konvejerių valdymas
Šiuolaikinės 3D programos dažnai apima sudėtingus atvaizdavimo konvejerius su keliais etapais, tokiais kaip:
- Atidėtasis atvaizdavimas (Deferred rendering)
- Šešėlių žemėlapių sudarymas (Shadow mapping)
- Ekrano erdvės aplinkos užtemimas (Screen-space ambient occlusion, SSAO)
- Papildomo apdorojimo efektai (švytėjimas, spalvų korekcija)
Kiekvienas iš šių etapų generuoja tarpinius rezultatus, kuriuos naudoja vėlesni etapai. Be tinkamo sinchronizavimo, galėtumėte skaityti iš FBO, į kurį ankstesnis etapas dar nebaigė rašyti.
Praktinė įžvalga: Kiekvienam jūsų atvaizdavimo konvejerio etapui, kuris rašo į FBO, kurį skaitys vėlesnis etapas, apsvarstykite galimybę įterpti sinchronizavimo tvorą. Jei grandine jungiate kelis FBO nuosekliai, jums gali prireikti sinchronizuoti tik tarp galutinio vieno FBO išvesties ir kito įvesties, o ne sinchronizuoti po kiekvieno piešimo iškvietimo etapo viduje.
Tarptautinis pavyzdys: Virtualios realybės mokymo simuliacija, kurią naudoja aviacijos ir kosmoso inžinieriai, gali atvaizduoti sudėtingas aerodinamines simuliacijas. Kiekvienas simuliacijos žingsnis gali apimti kelis atvaizdavimo etapus, kad būtų vizualizuota skysčių dinamika. Sinchronizavimo tvoros užtikrina, kad vizualizacija tiksliai atspindėtų simuliacijos būseną kiekviename žingsnyje, neleidžiant besimokančiajam matyti nenuoseklių ar pasenusių vizualinių duomenų.
4. Sąveika su „WebAssembly“ ar kitu vietiniu kodu
Jei jūsų „WebGL“ programa naudoja „WebAssembly“ (Wasm) skaičiavimams reiklioms užduotims, jums gali prireikti sinchronizuoti GPU operacijas su „Wasm“ vykdymu. Pavyzdžiui, „Wasm“ modulis gali būti atsakingas už viršūnių duomenų paruošimą ar fizikos skaičiavimų atlikimą, kurie vėliau perduodami į GPU. Ir atvirkščiai, GPU skaičiavimų rezultatus gali tekti apdoroti „Wasm“.
Kai duomenys turi judėti tarp naršyklės „JavaScript“ aplinkos (kuri valdo „WebGL“ komandas) ir „Wasm“ modulio, sinchronizavimo tvoros gali užtikrinti, kad duomenys būtų paruošti, prieš juos pasiekiant CPU veikiančiam „Wasm“ arba GPU.
5. Optimizavimas skirtingoms GPU architektūroms ir tvarkyklėms
GPU tvarkyklių ir aparatinės įrangos elgesys gali labai skirtis skirtinguose įrenginiuose ir operacinėse sistemose. Tai, kas puikiai veikia viename kompiuteryje, gali sukelti subtilių laiko problemų kitame. Sinchronizavimo tvoros suteikia patikimą, standartizuotą mechanizmą sinchronizavimui užtikrinti, todėl jūsų programa tampa atsparesnė šiems platformos specifikos niuansams.
`gl.fenceSync` ir `gl.clientWaitSync` supratimas
Panagrinėkime išsamiau pagrindines „WebGL“ funkcijas, susijusias su sinchronizavimo tvorų kūrimu ir valdymu:
`gl.fenceSync(condition, flags)`
- `condition`: Šis parametras nurodo sąlygą, kuriai esant tvora turėtų būti signalizuota. Dažniausiai naudojama reikšmė yra
gl.SYNC_GPU_COMMANDS_COMPLETE. Kai ši sąlyga įvykdoma, tai reiškia, kad visos komandos, kurios buvo pateiktos GPU priešgl.fenceSynciškvietimą, baigė vykdymą. - `flags`: Šis parametras gali būti naudojamas nurodyti papildomą elgesį. Su
gl.SYNC_GPU_COMMANDS_COMPLETEpaprastai naudojama vėliavėlė0, nurodanti jokio ypatingo elgesio, išskyrus standartinį baigimo signalizavimą.
Ši funkcija grąžina WebGLSync objektą, kuris atstovauja tvorai. Jei įvyksta klaida (pvz., neteisingi parametrai, nepakanka atminties), ji grąžina null.
`gl.clientWaitSync(sync, flags, timeout)`
Tai funkcija, kurią CPU naudoja norėdamas patikrinti sinchronizavimo tvoros būseną ir, jei reikia, laukti, kol ji bus signalizuota. Ji siūlo keletą svarbių parinkčių:
- `sync`:
WebGLSyncobjektas, grąžintas išgl.fenceSync. - `flags`: Kontroliuoja, kaip turėtų elgtis laukimas. Įprastos reikšmės apima:
0: Tikrina tvoros būseną. Jei ji nėra signalizuota, funkcija grįžta nedelsiant su būsena, nurodančia, kad ji dar nėra signalizuota.gl.SYNC_FLUSH_COMMANDS_BIT: Jei tvora dar nėra signalizuota, ši vėliavėlė taip pat nurodo GPU išvalyti visas laukiančias komandas prieš galbūt tęsiant laukimą.
- `timeout`: Nurodo, kiek laiko CPU gija turėtų laukti, kol tvora bus signalizuota.
gl.TIMEOUT_IGNORED: CPU gija lauks neribotai, kol tvora bus signalizuota. Tai dažnai naudojama, kai jums absoliučiai reikia, kad operacija būtų baigta prieš tęsiant.- Teigiamas sveikasis skaičius: Reiškia laukimo laiką nanosekundėmis. Funkcija grįš, jei tvora bus signalizuota arba jei pasibaigs nurodytas laikas.
Grąžinama gl.clientWaitSync reikšmė nurodo tvoros būseną:
gl.ALREADY_SIGNALED: Tvora jau buvo signalizuota, kai buvo iškviesta funkcija.gl.TIMEOUT_EXPIRED:timeoutparametru nurodytas laikas baigėsi, kol tvora nebuvo signalizuota.gl.CONDITION_SATISFIED: Tvora buvo signalizuota ir sąlyga buvo įvykdyta (pvz., GPU komandos baigtos).gl.WAIT_FAILED: Įvyko klaida laukimo operacijos metu (pvz., sinchronizavimo objektas buvo ištrintas arba neteisingas).
`gl.deleteSync(sync)`
Ši funkcija yra labai svarbi išteklių valdymui. Kai sinchronizavimo tvora buvo panaudota ir jos nebereikia, ji turėtų būti ištrinta, kad būtų atlaisvinti susiję GPU ištekliai. To nepadarius, gali atsirasti atminties nutekėjimas.
Pažangūs sinchronizavimo modeliai ir svarstymai
Nors `gl.SYNC_GPU_COMMANDS_COMPLETE` yra labiausiai paplitusi sąlyga, „WebGL 2.0“ (ir pagrindinis „OpenGL ES 3.0+“) siūlo detalesnį valdymą:
`gl.SYNC_FENCE` ir `gl.CONDITION_MAX`
„WebGL 2.0“ pristato `gl.SYNC_FENCE` kaip sąlygą `gl.fenceSync`. Kai tvora su šia sąlyga yra signalizuota, tai yra stipresnė garantija, kad GPU pasiekė tą tašką. Tai dažnai naudojama kartu su konkrečiais sinchronizavimo objektais.
`gl.waitSync` ir `gl.clientWaitSync` palyginimas
Nors `gl.clientWaitSync` gali blokuoti pagrindinę „JavaScript“ giją, `gl.waitSync` (pasiekiama kai kuriuose kontekstuose ir dažnai įdiegta naršyklės „WebGL“ sluoksnyje) gali pasiūlyti sudėtingesnį valdymą, leisdama naršyklei laukimo metu atlikti kitas užduotis. Tačiau standartiniame „WebGL“ daugumoje naršyklių `gl.clientWaitSync` yra pagrindinis mechanizmas CPU laukimui.
CPU-GPU sąveika: kliūčių vengimas
Sinchronizavimo tikslas yra ne priversti CPU be reikalo laukti GPU, o užtikrinti, kad GPU baigtų savo darbą prieš CPU bandant naudoti ar remtis tuo darbu. Per didelis `gl.clientWaitSync` su `gl.TIMEOUT_IGNORED` naudojimas gali paversti jūsų GPU pagreitintą programą nuoseklaus vykdymo konvejeriu, paneigiant lygiagretaus apdorojimo privalumus.
Geroji praktika: Kai tik įmanoma, struktūrizuokite savo atvaizdavimo ciklą taip, kad CPU galėtų tęsti kitų nepriklausomų užduočių vykdymą, laukdamas GPU. Pavyzdžiui, laukdamas atvaizdavimo etapo pabaigos, CPU galėtų ruošti duomenis kitam kadrui arba atnaujinti žaidimo logiką.
Globalus pastebėjimas: Įrenginiai su žemesnės klasės GPU ar integruota grafika gali turėti didesnį GPU operacijų vėlavimą. Todėl atidus sinchronizavimas naudojant tvoras tampa dar svarbesnis šiose platformose, siekiant išvengti trūkčiojimo ir užtikrinti sklandžią vartotojo patirtį įvairioje pasaulyje naudojamoje aparatinėje įrangoje.
Kadrų buferiai ir tekstūrų paskirties objektai
Naudojant kadrų buferio objektus (FBO) „WebGL 2.0“, dažnai galite efektyviau pasiekti sinchronizavimą tarp atvaizdavimo etapų, nebūtinai reikalaudami aiškių sinchronizavimo tvorų kiekvienam perėjimui. Pavyzdžiui, jei atvaizduojate į FBO A ir iš karto naudojate jo spalvų buferį kaip tekstūrą atvaizdavimui į FBO B, „WebGL“ įgyvendinimas dažnai yra pakankamai protingas, kad valdytų šią priklausomybę viduje. Tačiau, jei jums reikia nuskaityti duomenis iš FBO A atgal į CPU prieš atvaizduojant į FBO B, tada sinchronizavimo tvora tampa būtina.
Klaidų tvarkymas ir derinimas
Sinchronizavimo problemas gali būti ypač sunku derinti. Lenktynių sąlygos dažnai pasireiškia sporadiškai, todėl jas sunku atkurti.
- Gausiai naudokite `gl.getError()`: Po bet kokio „WebGL“ iškvietimo patikrinkite, ar nėra klaidų.
- Izoliuokite problemišką kodą: Jei įtariate sinchronizavimo problemą, pabandykite komentuoti dalį savo atvaizdavimo konvejerio ar duomenų perdavimo operacijų, kad nustatytumėte šaltinį.
- Vizualizuokite konvejerį: Naudokite naršyklės kūrėjo įrankius (pvz., „Chrome“ „DevTools for WebGL“ arba išorinius profiliavimo įrankius), kad patikrintumėte GPU komandų eilę ir suprastumėte vykdymo eigą.
- Pradėkite nuo paprasto: Jei įgyvendinate sudėtingą sinchronizavimą, pradėkite nuo paprasčiausio galimo scenarijaus ir palaipsniui didinkite sudėtingumą.
Globali įžvalga: Derinimas skirtingose naršyklėse („Chrome“, „Firefox“, „Safari“, „Edge“) ir operacinėse sistemose („Windows“, „macOS“, „Linux“, „Android“, „iOS“) gali būti sudėtingas dėl skirtingų „WebGL“ įgyvendinimų ir tvarkyklių elgsenos. Teisingas sinchronizavimo tvorų naudojimas padeda kurti programas, kurios elgiasi nuosekliau visame šiame pasauliniame spektre.
Alternatyvos ir papildančios technikos
Nors sinchronizavimo tvoros yra galingos, jos nėra vienintelis įrankis sinchronizavimo įrankių dėžėje:
- Kadrų buferio objektai (FBO): Kaip minėta, FBO leidžia atvaizduoti ne ekrane ir yra esminiai daugiapakopiam atvaizdavimui. Naršyklės įgyvendinimas dažnai tvarko priklausomybes tarp atvaizdavimo į FBO ir jo naudojimo kaip tekstūros kitame žingsnyje.
- Asinchroninis šešėlių kompiliavimas: Šešėlių kompiliavimas gali būti daug laiko reikalaujantis procesas. „WebGL 2.0“ leidžia asinchroninį kompiliavimą, todėl pagrindinė gija neturi sustoti, kol apdorojami šešėliai.
- `requestAnimationFrame`: Tai standartinis mechanizmas atvaizdavimo atnaujinimų planavimui. Jis užtikrina, kad jūsų atvaizdavimo kodas veiktų prieš pat naršyklei atliekant kitą perpiešimą, o tai lemia sklandesnes animacijas ir geresnį energijos vartojimo efektyvumą.
- „Web Workers“: Dideliems, CPU reikalaujantiems skaičiavimams, kuriuos reikia sinchronizuoti su GPU operacijomis, „Web Workers“ gali perkelti užduotis iš pagrindinės gijos. Duomenų perdavimas tarp pagrindinės gijos (valdančios „WebGL“) ir „Web Workers“ gali būti sinchronizuotas.
Sinchronizavimo tvoros dažnai naudojamos kartu su šiomis technikomis. Pavyzdžiui, galite naudoti `requestAnimationFrame` savo atvaizdavimo ciklui valdyti, ruošti duomenis „Web Worker“, o tada naudoti sinchronizavimo tvoras, kad užtikrintumėte, jog GPU operacijos būtų baigtos prieš skaitant rezultatus ar pradedant naujas priklausomas užduotis.
GPU-CPU sinchronizavimo ateitis internete
Interneto grafikai toliau tobulėjant, su sudėtingesnėmis programomis ir didesnio tikslumo reikalavimais, efektyvus sinchronizavimas išliks kritiškai svarbia sritimi. „WebGL 2.0“ gerokai patobulino sinchronizavimo galimybes, o ateities interneto grafikos API, tokios kaip „WebGPU“, siekia suteikti dar tiesiogesnį ir smulkesnį GPU operacijų valdymą, potencialiai siūlydamos našesnius ir aiškesnius sinchronizavimo mechanizmus. Supratimas apie „WebGL“ sinchronizavimo tvorų principus yra vertingas pagrindas norint įvaldyti šias ateities technologijas.
Išvada
„WebGL Sync Fences“ yra gyvybiškai svarbus primityvas, siekiant patikimo ir našaus GPU-CPU sinchronizavimo interneto grafikos programose. Atidžiai įterpdami ir laukdami sinchronizavimo tvorų, kūrėjai gali išvengti lenktynių sąlygų, pasenusių duomenų ir užtikrinti, kad sudėtingi atvaizdavimo konvejeriai veiktų teisingai ir efektyviai. Nors joms reikia apgalvoto požiūrio į įgyvendinimą, kad būtų išvengta nereikalingų sustojimų, jų siūlomas valdymas yra nepakeičiamas kuriant aukštos kokybės, daugiaplatformes „WebGL“ patirtis. Šių sinchronizavimo primityvų įvaldymas leis jums peržengti interneto grafikos galimybių ribas, teikiant sklandžias, greitai reaguojančias ir vizualiai stulbinančias programas vartotojams visame pasaulyje.
Pagrindinės išvados:
- GPU operacijos yra asinchroninės; sinchronizavimas yra būtinas.
- „WebGL Sync Fences“ (pvz., `gl.SYNC_GPU_COMMANDS_COMPLETE`) veikia kaip signalai tarp CPU ir GPU.
- Naudokite `gl.fenceSync` norėdami įterpti tvorą ir `gl.clientWaitSync` norėdami jos laukti.
- Būtina skaitant pikselių duomenis, perduodant duomenis ir valdant sudėtingus atvaizdavimo konvejerius.
- Visada ištrinkite sinchronizavimo tvoras naudodami `gl.deleteSync`, kad išvengtumėte atminties nutekėjimo.
- Subalansuokite sinchronizavimą su lygiagretumu, kad išvengtumėte našumo kliūčių.
Įtraukdami šias koncepcijas į savo „WebGL“ kūrimo darbo eigą, galite žymiai pagerinti savo grafikos programų stabilumą ir našumą, užtikrindami aukštesnę patirtį savo pasaulinei auditorijai.